package com.whu.MenuHub.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.gson.Gson;
import com.whu.MenuHub.domain.Food;
import com.whu.MenuHub.domain.FoodComment;
import com.whu.MenuHub.domain.FoodDTO;
import com.whu.MenuHub.domain.FoodRecResult;
import com.whu.MenuHub.exception.MenuHubException;
import com.whu.MenuHub.service.FoodCommentService;
import com.whu.MenuHub.service.FoodFlavorService;
import com.whu.MenuHub.service.FoodService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.models.auth.In;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@CrossOrigin
@RequestMapping("/foods")
@Api(tags = "食品信息管理API")
public class FoodController {
    @Autowired
    FoodService foodService;

    @Autowired
    FoodCommentService commentService;
    @Autowired
    FoodFlavorService flavorService;
    //获取食品信息
    @GetMapping("/id/{id}")
    @ApiOperation("根据id获取食品信息")
    public Food getFoodByID(@ApiParam("食品ID")@PathVariable Integer id){
        return foodService.getFoodByFoodID(id);
    }

    //管理员才有权限增加食品，食品的基本信息和口味信息同时增加，使用dto封装
    @PostMapping("")
    @ApiOperation("新增一条食品记录")
    @PreAuthorize("hasAnyAuthority('all')")
    public Food InsertFood(@ApiParam("食品信息")@RequestBody FoodDTO foodDTO) throws MenuHubException {
        return foodService.insertFood(foodDTO);
    }

    //管理员才有权限修改食品，食品的基本信息和口味信息同时修改，使用dto封装
    @PutMapping("")
    @ApiOperation("修改一条食品记录")
    @PreAuthorize("hasAnyAuthority('all')")
    public void updateFood(@ApiParam("食品信息")@RequestBody FoodDTO foodDTO) throws MenuHubException {
        foodService.updateFoodByID(foodDTO);
    }

    //管理员才有权限删除食品，先删除食品口味，然后再删除食品
    @DeleteMapping("/{id}")
    @ApiOperation("删除一条食品记录")
    @PreAuthorize("hasAnyAuthority('all')")
    public void deleteFood(@ApiParam("食品ID")@PathVariable Integer id) throws MenuHubException {
        foodService.deleteFoodByID(id);
    }

    //分页查询，查询的条件可以为空，查询返回食品的基本信息
    @ApiOperation("用户根据条件查询食品")
    @GetMapping("")
    public IPage<Food> findFood(@ApiParam("食品关键字")@RequestParam(value = "keyword",required = false) String keyword,
                                                   @ApiParam("食品最低价格") @RequestParam(value = "minPrice",required = false)  Integer minPrice,
                                                   @ApiParam("食品最高价格") @RequestParam(value = "maxPrice",required = false)  Integer maxPrice,
                                                   @ApiParam("排序字段") @RequestParam(value = "orderField",required = false)  String orderField,
                                                   @ApiParam("排序方式") @RequestParam(value = "orderType",required = false)  String orderType,
                                                   @ApiParam("食品类别") @RequestParam(value = "label",required = false)  String label,
                                                   @ApiParam("页码")@RequestParam(defaultValue = "0")Integer pageNum,
                                                   @ApiParam("每页记录数") @RequestParam(defaultValue = "10")Integer pageSize){
        Map<String,Object> condition=new HashMap<>();
        if(keyword!=null) {
            condition.put("keyword",keyword);
        }
        if(maxPrice!=null) {
            condition.put("maxPrice",maxPrice);
        }
        if(minPrice!=null) {
            condition.put("minPrice",minPrice);
        }
        if(label!=null) {
            condition.put("label",label);
        }
        //判断是否需要排序，排序的方式只有三种：点赞量，销量和评分
        if(orderField!=null&&(orderField.equals("saleNumber")||orderField.equals("foodStar")||orderField.equals("foodScore")||orderField.equals("price"))){
            condition.put("orderField",orderField);
        }
        //判断排序的类型
        if(orderType!=null){
            condition.put("orderType",orderType);
        }
        return foodService.findFoods(condition, pageNum, pageSize);
    }
    @ApiOperation("商家根据条件查询食品")
    @GetMapping("/owner")
    public List<Food> findAllFood(@ApiParam("食品关键字")@RequestParam(value = "keyword",required = false) String keyword,
                                @ApiParam("食品最低价格") @RequestParam(value = "minPrice",required = false)  Integer minPrice,
                                @ApiParam("食品最高价格") @RequestParam(value = "maxPrice",required = false)  Integer maxPrice,
                                @ApiParam("排序字段") @RequestParam(value = "orderField",required = false)  String orderField,
                                @ApiParam("排序方式") @RequestParam(value = "orderType",required = false)  String orderType,
                                @ApiParam("食品类别") @RequestParam(value = "label",required = false)  String label){
        Map<String,Object> condition=new HashMap<>();
        if(keyword!=null) {
            condition.put("keyword",keyword);
        }
        if(maxPrice!=null) {
            condition.put("maxPrice",maxPrice);
        }
        if(minPrice!=null) {
            condition.put("minPrice",minPrice);
        }
        if(label!=null) {
            condition.put("label",label);
        }
        //判断是否需要排序，排序的方式只有三种：点赞量，销量和评分
        if(orderField!=null&&(orderField.equals("saleNumber")||orderField.equals("foodStar")||orderField.equals("foodScore")||orderField.equals("price"))){
            condition.put("orderField",orderField);
        }
        //判断排序的类型
        if(orderType!=null){
            condition.put("orderType",orderType);
        }
        return foodService.findAllFood(condition);
    }

    //获取近7日销量最高的食物
    @GetMapping("/recentHot")
    @ApiOperation("获取近7日销量最高的食品信息")
    List<Food> getHotFoodWithin7Day(){
        return foodService.getHotFoodWithin7Day();
    }

    //获取食品详细信息，包含口味和评价,商品的基本信息没有获取到，页面传递的过程中将信息传递，然后再合并
    @GetMapping("/detail/{id}")
    @ApiOperation("根据id获取食品信息")
    public FoodDTO getFoodDetailByID(@ApiParam("食品ID")@PathVariable Integer id,
                                     @ApiParam("页码")@RequestParam(defaultValue = "0")Integer pageNum,
                                     @ApiParam("每页记录数") @RequestParam(defaultValue = "10")Integer pageSize){
        FoodDTO foodDTO=new FoodDTO();
        //如果表格中没有，无法查找
        if(foodService.getFoodByFoodID(id)==null)return null;
        foodDTO.setId(id);
        foodDTO.setFoodFlavor(flavorService.getfalvorByFoodID(id));
        Map<String,Object> condition=new HashMap<>();
        condition.put("foodID", id);
        foodDTO.setCommentList(commentService.getComments(condition, pageNum, pageSize));
        return foodDTO;
    }

    //根据照片识别食物
    @GetMapping("/foodRecognize/{photoURL}")
    @ApiOperation("根据输入的照片智能识别食物的内容")
    public List<FoodRecResult> recognizeFood(@PathVariable String photoURL)throws MenuHubException{
        try{
            System.out.println(photoURL);
            //李妃 python环境
            String anacondaUrl="python";
            //获取python的执行文件地址
            String apiurL=new File(".").getCanonicalPath()+"/python-api/foodReconize2.py";
            //传递的参数
            photoURL="/photo/food/"+photoURL;
            String[] arg = new String[]{anacondaUrl, apiurL,photoURL};
            Process proc = Runtime.getRuntime().exec(arg);
            int res = proc.waitFor();
            List<FoodRecResult>results=new ArrayList<>();
            if (res == 0) {
                System.out.println("成功执行");
                //成功执行 获取输出信息
                String line=null;
                BufferedReader inData = new BufferedReader(new InputStreamReader(proc.getInputStream(), "gb2312"));
                //封装数据并返回
                int index=0;
                FoodRecResult result=new FoodRecResult();
                while ((line = inData.readLine()) != null) {
                    System.out.println(line);
                    switch(index){
                        case 0:result.setFoodName(line);break;
                        case 1:result.setLabel(line);break;
                        case 2:result.setCalorie(Integer.parseInt(line));break;
                    }
                    index++;
                    if(index==3){
                        index=0;
                        //将结果放到result中
                        Food food=foodService.findFoodByFoodName(result.getFoodName());
                        result.setId(food.getId());
                        result.setPhoto(food.getPhoto());
                        result.setPrice(food.getPrice());
                        result.setFoodScore(food.getFoodScore());
                        result.setFoodStar(food.getFoodStar());
                        result.setSaleNumber(food.getSaleNumber());
                        result.setFoodFlavor(flavorService.getfalvorByFoodID(food.getId()));
                        results.add(result);
                        result=new FoodRecResult();
                    }
                }
                inData.close();
                return results;
            }else{
                System.out.println("执行错误");
                //未成功执行 获取错误输出信息
                String line=null;
                BufferedReader inError = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "gb2312"));
                while ((line = inError.readLine()) != null) {
                    System.out.println(line);
                }
                inError.close();
            }
            proc.waitFor();
        }catch (IOException | InterruptedException e){
            throw new MenuHubException(MenuHubException.ErrorType.IO_EXCEPTION,"获取协同过滤的推荐结果失败");
        }
        return null;
    }

    //每天零点更新食品的评价关键词
    @Scheduled(cron="0 0 0 * * ?")
    @GetMapping("/keyword")
    @ApiOperation("获取食品评价的关键词")
    public void getfoodKeyWord() throws MenuHubException{
        try{
            //李妃 python环境
            String anacondaUrl="python";
            //获取python的执行文件地址
            String apiurL=new File(".").getCanonicalPath()+"/python-api/tagPredict.py";
            //传递的参数
            String[] arg = new String[]{anacondaUrl, apiurL};
            Process proc = Runtime.getRuntime().exec(arg);
            int res = proc.waitFor();
            if (res != 0) {
                //未成功执行 获取错误输出信息
                String line=null;
                BufferedReader inError = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "utf-8"));
                while ((line = inError.readLine()) != null) {
                        System.out.println(line);
                }
                inError.close();
                }
                proc.waitFor();
        }catch (IOException | InterruptedException e){
            throw new MenuHubException(MenuHubException.ErrorType.IO_EXCEPTION,"执行更新相似性矩阵的python接口失败");
        }
    }

    }
